import traceback

import requests
import json

class HTTP:

    def __init__(self,writer):
        self.session = requests.session()   # session会话管理对象
        self.url = "" # http://10.36.176.22:8082/inter/HTTP/ # 基础URL
        self.resp = None        # 响应对象
        self.jsonres = None     # 响应json格式数据
        self.relations = {}  # 存储关联数据,字典格式
        self.writer = writer
        self.r = 0 # 执行的行号, 执行哪一行 写入哪一行

    def set_url(self,url): # http://10.36.176.22:8082/inter/HTTP/
        """
        设置基础URL地址
        :param url:
        :return:
        """
        self.url = url
        print(self.url)
        self.write_excel(True,self.url)

    def post(self,intername,payload=None):# getUserInfo   id={id}  id=1 {token}
        """
        封装post请求
        :param intername: 接口名称
        :param payload: 字符串格式的参数数据
        :return:
        """   # username=allen&password=123456
        path =self.url + intername # 将基础URL地址与接口名称进行拼接
        payload = self.get_relation(payload) # id={id}  id=1
        payload = self.get_data(payload) # 调用数据转换函数,将字符串参数转换为字典
        try: # 发起请求失败时,捕获异常
            self.resp = self.session.post(path,data=payload)
        except Exception as e:
            self.resp = None

        if self.resp is None:
            self.jsonres = None
        else:
            try: # 尝试将 响应文本数据转换为 字典格式数据
                self.jsonres = json.loads(self.resp.text)
                print(self.jsonres)
                self.write_excel(True,str(self.jsonres))
            except Exception as e: # 转换失败时, 捕获异常
                self.write_excel(False,str(traceback.format_exc()))
                self.jsonres = None

    def get_data(self, payload): # username=allen&password=123456  id=1
        """
        将字符串数据 转换为字典格式数据
        :param payload: 字符串数据
        :return:
        """
        d = {}
        if payload is None or payload == "":
            return None
        else:
            list1 = payload.split('&')
            for str1 in list1:
                index = str1.find('=')
                key = str1[:index]
                value = str1[index + 1:]
                d[key] = value

            return d

    def save_relation(self,relationkey,jsonkey):
        """
        保存关联数据
        :param relationkey: 保存到关联字典时的key
        :param jsonkey:  从响应字典中取值时的key
        :return:
        """
        # self.relations[key] = value  # self.jsonres["token"]
        try:
            value = self.jsonres[jsonkey]
        except Exception as e:
            self.write_excel(False,str(traceback.format_exc()))
            value = None
        self.relations[relationkey] = value
        print(self.relations)
        self.write_excel(True,str(self.relations))

    def get_relation(self, strkey):  # id={id} {token}
        """
        从关联字典获取指定key的值
        :param strkey: 必须满足 {key}
        :return:
        """
        if strkey is None or strkey == "":
            return None

        value = None
        for key in self.relations.keys():
            value = strkey.replace("{"+key+"}",self.relations[key])
        return value

    def add_header(self,headerkey,relationkey):
        """
        添加请求头
        :param headerkey: 请求头添加时的key
        :param relationkey: 添加到请求头中的数据 取值时的key
        :return:
        """
        # http.session.headers["token"] = http.get_relation("token")
        self.session.headers[headerkey] = self.get_relation(relationkey)
        print(self.session.headers)
        self.write_excel(True,str(self.session.headers))

    def assert_equal(self,key,expect):
        """
        断言期望数据与实际结果中key对应数据 一致
        :param key: 实际结果取值需要的key
        :param expect: 期望结果
        :return:
        """
        if self.jsonres is None:
            return False
        try:
            if str(self.jsonres[key]) == str(expect):
                print("期望结果为:%s, 实际结果为: %s,期望与实际一致, 测试用例执行通过!"%
                      (str(expect),str(self.jsonres[key])))
                self.write_excel(True,str(self.jsonres))
                return True
            else:
                print("期望结果为:%s, 实际结果为: %s,期望与实际不一致, 测试用例执行失败!" %
                      (str(expect), str(self.jsonres[key])))
                self.write_excel(False, str(self.jsonres))
                return False
        except Exception as e:

            self.write_excel(False,str(traceback.format_exc()))

    def assert_equals(self,expect):
        """
        断言期望结果的每一个key的数据与实际结果中每个key的数据完全相等
        :param expect: 期望结果(满足字典格式的字符串数据)
        :return:
        """
        if self.jsonres is None:
            return False
        expect = json.loads(expect) # 将符合字典格式的字符串数据, 转换为字典数据
        for key in expect.keys():
            if str(self.jsonres[key]) != str(expect[key]):
                print("期望结果为:%s, 实际结果为: %s, 期望与实际不一致, 测试用例执行失败!"
                      %(str(expect[key]),str(self.jsonres[key])))
                self.write_excel(False, str(self.jsonres))
                return False
        # 循环结束, 没有出现期望结果与实际结果不一致的情况,则返回True
        self.write_excel(True, str(self.jsonres))
        return True

    def assert_contains(self,expect):
        """
        断言期望字符串包含在响应文本中
        :param expect: 期望结果(字符串数据)
        :return:
        """
        if self.resp is None:
            return False

        if self.resp.text.__contains__(expect):
            print("期望结果为:%s, 实际结果为: %s, 期望结果包含在实际响应文本中, 测试用例执行通过!"
                  % (str(expect), str(self.resp.text)))
            self.write_excel(True, str(self.resp.text))
            return True
        else:
            print("期望结果为:%s, 实际结果为: %s, 期望结果不包含在实际响应文本中, 测试用例执行失败!"
                  % (str(expect), str(self.resp.text)))
            self.write_excel(False, str(self.resp.text))
            return False

    def write_excel(self,status,value):
        """
        反向写回excel中
        :param status: 关键字函数运行状态
        :param value: 写入的数据
        :return:
        """
        if status == True:
            self.writer.write(self.r,7,"PASS","3")
        else:
            self.writer.write(self.r,7,"FAIL","2")

        if len(str(value)) > 1024:
            value = value[:1024]

        self.writer.write(self.r,8,value)


